package com.itouch.bracelet.bluetooth;

import java.util.ArrayList;
import java.util.List;

import com.itouch.bracelet.bean.Child;
import com.itouch.bracelet.bean.LoginUser;

/**
 * 

* @ClassName: BluetoothUtil 

* @Description: TODO(蓝牙数据包校验工具类) 

* @author sunshineHu hucx@itouch.com.cn

* @date 2015年1月16日 上午9:27:11 

*
 */
public class BluetoothUtil {
	//CRC16 校验表
	static int[] crc16_ccitt_table={ 
		  0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 
		  0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 
		  0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 
		  0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 
		  0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 
		  0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 
		  0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 
		  0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 
		  0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 
		  0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 
		  0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 
		  0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 
		  0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 
		  0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 
		  0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 
		  0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 
		  0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 
		  0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 
		  0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
		  0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 
	      0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 
		  0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 
		  0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 
		  0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 
		  0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 
		  0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 
		  0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 
		  0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 
		  0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 
		  0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 
		  0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 
		  0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
		};
	
	

	/**
	 * 
	
	* @Title: unpackData 
	
	* @Description: TODO(解析蓝牙数据包,如果有多个数据包同时接受需要拆解) 
	
	* @param @param packet
	* @param @return    设定文件 
	
	* @return boolean    返回类型 
	
	* @throws
	 */
	public static List<BluetoothPacket> unpackData(byte[] content){
		List<BluetoothPacket> list=new ArrayList<BluetoothPacket>();
		int lenth=content.length;
		int current=0;
		if(content[0]==2){//校验首字符
			while(current<lenth){
				int datalen=content[current+7];
				if(current+datalen+11>lenth){
					//长度校验不合格
					break;
				}
				byte[] temp=new byte[datalen+11];
				System.arraycopy(content, current, temp, 0, temp.length);
				BluetoothPacket packet=new BluetoothPacket();
				packet.setRaw(temp);
				if(parseData(packet)){
					list.add(packet);
				}
				current=current+datalen+11;
			}
		}
		
		return list;
	}
	
	/**
	 * 
	
	* @Title: parseData 
	
	* @Description: TODO(解析校验数据包) 
	
	* @param @param rawpack
	* @param @return    设定文件 
	
	* @return boolean    返回类型 
	
	* @throws
	 */
	private static boolean parseData(BluetoothPacket rawpack){
		
		try {
			byte[] rawdata=rawpack.getRaw();
			int lenth=rawdata.length;
			if(rawdata[0]!=2||rawdata[lenth-1]!=3){
				return false;
			}
			int datalen=rawdata[7];
			rawpack.setHeader((byte)2);
			rawpack.setEnd((byte)3);
			byte[] cmd=new byte[4];
			byte[] content=new byte[lenth-4];
			byte[] id={rawdata[5],rawdata[6]};
			byte[] data=new byte[datalen];
			byte[] verify={rawdata[lenth-3],rawdata[lenth-2]};
			
			System.arraycopy(rawdata, 1, cmd, 0, 4);//功能码
			System.arraycopy(rawdata, 1, content, 0, lenth-4);
			System.arraycopy(rawdata, 8, data, 0, datalen);
			
			rawpack.setCmd(cmd);
			rawpack.setContent(content);
			rawpack.setId(id);
			rawpack.setLenth((byte)datalen);
			rawpack.setData(data);
			rawpack.setVerify(verify);
			
			//解析数据类型
			if(datalen==4){
				if(data[2]==(byte)0xA1&&data[3]==(byte)0x20){
					rawpack.setType(BluetoothType.WARN_TAKE_INCORRECT);
				}else if(data[2]==(byte)0xA1&&data[3]==(byte)0x10){
					rawpack.setType(BluetoothType.WARN_TAKE_CORRECT);
				}else if(data[2]==(byte)0xA1&&data[3]==(byte)0x11){
					rawpack.setType(BluetoothType.WARN_STEAL);
				}
			}else if(datalen==5){
				if(data[3]==(byte)0xA3&&data[4]==1){
					rawpack.setType(BluetoothType.WARN_LOST);
				}else if(data[3]==(byte)0xA4&&data[4]==1){
					rawpack.setType(BluetoothType.WARN_LOW_ENERGY);
				}else if(data[2]==(byte)0xA0){
					rawpack.setType(BluetoothType.WARN_OUT_OF_RANGE_BABY);
				}else if(data[2]==(byte)0xB0){
					rawpack.setType(BluetoothType.WARN_OUT_OF_RANGE_CHILD);
				}
			}else if(datalen==6){
				if(data[3]==(byte)0xA2){
					rawpack.setType(BluetoothType.DATA_TEMPERATURE);
				}else if(data[0]==(byte)0xC2){
					rawpack.setType(BluetoothType.DATA_STATUS);
				}
			}else if(datalen==7){
				if(data[0]==(byte)0xC1){
					rawpack.setType(BluetoothType.DATA_STEP_MOTHER);
				}else if(data[0]==(byte)0xB1){
					rawpack.setType(BluetoothType.DATA_STEP_CHILD);
				}
			}
			
			if(verifyData(rawpack, true)){
				return true;
			}else{
				return false;
			}
		} catch (Exception e) {
			// TODO: handle exception
			return false;
		}
	}
	
	
	/**
	 * 
	
	* @Title: verifyData 
	
	* @Description: TODO(CRC校验) 
	
	* @param @param packet
	* @param @param isIn
	* @param @return    设定文件 
	
	* @return boolean    返回类型 
	
	* @throws
	 */
	public static boolean verifyData(BluetoothPacket packet,boolean isIn){
		
		byte[] ver=CRC16(0xffff, packet.getContent(), packet.getContent().length);
		
		if(isIn){
			byte[] verify=packet.getVerify();
			if(verify[0]==ver[0]&&verify[1]==ver[1]){
				return true;
			}else{
				return false;
			}
		}else{
			packet.setVerify(ver);
		}
		
		return true;
	}
	
	
	//CRC校验方法
	private static byte[] CRC16(int reg_init, byte message[], int len){
		int crc_reg = reg_init;   
		int j=0;
		while (len-->0)   {
		  crc_reg = (crc_reg >> 8) ^ crc16_ccitt_table[(crc_reg ^ message[j]) & 0xff]; 
		  j++;
		}
	    crc_reg=crc_reg^0xffff;
	    byte[] result=new byte[2];
	    result[1]=(byte) crc_reg;
	    result[0]=(byte) (crc_reg>>8);
	    
	    return result;
	}
	
	/**
	 * 
	
	* @Title: packetData 
	
	* @Description: TODO(数据包封装) 
	
	* @param @param packet
	* @param @return    设定文件 
	
	* @return boolean    返回类型 
	
	* @throws
	 */
	public static boolean packetData(BluetoothPacket packet,int type){
		try {
			
			int len=packet.getData().length+11;//数据包总长度
			byte[] raw=new byte[len];
			raw[0]=2;
			raw[len-1]=3;
			
			byte[] before=new byte[4];
			if(type==1){
				byte[] func={(byte)0x3C ,(byte)0x53 ,(byte)0x45 ,(byte)0x4D };//发送功能码  
				before=func;
			}else if(type==2){
				byte[] func={(byte)0x3E, (byte)0x53, (byte)0x45, (byte)0x43};
				before=func;
			}
			
			raw[7]=(byte) packet.getData().length;//数据长度
			
			
			System.arraycopy(before, 0, raw, 1, before.length);
			
			System.arraycopy(packet.getId(), 0, raw, 5, packet.getId().length);
			
			System.arraycopy(packet.getData(), 0, raw, 8, packet.getData().length);
			
			byte[] content=new byte[len-4];
			System.arraycopy(raw, 1, content, 0, len-4);
			packet.setContent(content);
			
			verifyData(packet, false);
			
			raw[len-3]=packet.getVerify()[0];
			raw[len-2]=packet.getVerify()[1];
			
			packet.setRaw(raw);
		} catch (Exception e) {
			// TODO: handle exception
			return false;
		}
		return true;
	}
	
	
	//计步器数据解析
	//增加了耦合度，不好。。。
	public static int getSteps(BluetoothPacket packet){
		
		//计步器数据
		byte[] data={packet.getData()[3],packet.getData()[4],packet.getData()[5],packet.getData()[6]};
		//int steps=(data[0]<<24)|(data[1]<<16)|(data[2]<<8)|(data[3]); 
		
		int steps = (int) ( ((data[0] & 0xFF)<<24)  
		            |((data[1] & 0xFF)<<16)  
		            |((data[2] & 0xFF)<<8)  
		            |(data[3] & 0xFF));  
		
		return steps;
	}
	
	
	
	/**
	 * 根据该数据包得到当前用户下的孩子对象
	 * @param user
	 * @param packet
	 * @return
	 */
	public static Child getChild(LoginUser user,BluetoothPacket packet){
		
		if(packet.getType()==BluetoothType.DATA_TEMPERATURE){
			//体温数据
			if(user.getChildlist().size()>0){
				for(Child child:user.getChildlist()){
					String deviceNo=child.getDeviceNo();
					if(deviceNo!=null&&deviceNo.length()==5&&deviceNo.contains(":")){
						String[] devcode=deviceNo.split(":");
						int part1=Integer.valueOf(devcode[0],16);
						int part2=Integer.valueOf(devcode[1],16);
						if(packet.getData()[0]==(byte)part1&&packet.getData()[1]==(byte)part2){
							//孩子匹配成功
							return child;
						}
						
					}
				}
			}
		}
		
		return null;
	}
	
	
	
	/***
	 * 根据设备号判断手环类型
	 * 1婴儿手环
	 * 2儿童手环
	 * 0无法识别
	 */
	public static int getDeviceType(String deviceNo){
		
		if(deviceNo.length()==5&&deviceNo.contains(":")){
			String[] devs=deviceNo.split(":");
			if(devs.length==2){
				int high=Integer.valueOf(devs[0], 16);
				if((high>>7)==1){
					return 2;
				}else{
					return 1;
				}
			}
		}
		
		return 0;
	}
	
	/***
	 * 根据数据包id校验是否为当前孩子
	 * @return
	 */
	public static boolean verifyChild(Child child,byte[] deviceNo){
		
		String device=child.getDeviceNo();
		if(getDeviceType(device)!=0){
			String[] devs=device.split(":");
			int high=Integer.valueOf(devs[0], 16);
			int low=Integer.valueOf(devs[1], 16);
			if((high==(deviceNo[0]&0xFF))&&(low==(deviceNo[1]&0xFF))){
				return true;
			}
		}
		
		return false;
	}
	
	
}
